package com.learning.generator.core;

import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.builder.CustomFile;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import java.sql.Types;
import java.util.*;
import java.util.function.Consumer;

import static com.learning.generator.core.DefaultBaseInfoConstant.*;


// 自定义模板生成
public class FastCodeGeneratorPlus {
    public static void main(String[] args) {
        FastAutoGenerator.create(JDBC_URL_MAN, JDBC_UserName, JDBC_Password)
                // 全局配置
                .globalConfig(configGlobal())

                // java和数据库字段的类型转换
                .dataSourceConfig(configDataSource())

                // 包配置
                .packageConfig(configPackage())

                // 策略配置
                .strategyConfig(configStrategy())

                // 自定义生文件
                .injectionConfig(configInjection())
                // 配置模板
                .templateConfig(configTemplate())
                // 使用Freemarker引擎模板，默认的是Velocity引擎模板
                .templateEngine(new CustomerTemplateEngine())
                .execute();
    }

    public static void execute() {
        FastAutoGenerator.create(JDBC_URL_MAN, JDBC_UserName, JDBC_Password)
                // 全局配置
                .globalConfig(configGlobal())

                // java和数据库字段的类型转换
                .dataSourceConfig(configDataSource())

                // 包配置
                .packageConfig(configPackage())

                // 策略配置
                .strategyConfig(configStrategy())

                // 自定义生文件
                .injectionConfig(configInjection())
                // 配置模板
                .templateConfig(configTemplate())
                // 使用Freemarker引擎模板，默认的是Velocity引擎模板
                .templateEngine(new CustomerTemplateEngine())
                .execute();
    }

    private static Consumer<TemplateConfig.Builder> configTemplate() {
        return builder -> builder.disable(
                // TemplateType.ENTITY,
                TemplateType.XML,
                // TemplateType.SERVICE_IMPL,
                // TemplateType.SERVICE,
                // TemplateType.MAPPER
                TemplateType.CONTROLLER
        );
    }

    private static Consumer<InjectionConfig.Builder> configInjection() {
        return builder -> {
            Map<String, Object> paramMap = new HashMap<>();

            List<CustomFile> customFiles = new ArrayList<>();

            CustomFile voCustomFile = new CustomFile.Builder()
                    .fileName(".java")
                    .formatNameFunction(tableInfo -> "VO")
                    .packageName(CONTROLLER_PACKAGE + ".vo")
                    .templatePath("/templates/vo.java.ftl")
                    .enableFileOverride()
                    .build();


            customFiles.add(voCustomFile);
            builder.customMap(paramMap)
                    .customFile(customFiles);
        };
    }

    private static Consumer<StrategyConfig.Builder> configStrategy() {
        return builder ->
                builder.enableCapitalMode()// 驼峰
                        .enableSkipView()// 跳过视图
                        .disableSqlFilter()
                        .addTablePrefix(table_prefix) // 增加过滤表前缀
//                            .addTableSuffix("_db") // 增加过滤表后缀
//                            .addFieldPrefix("t_") // 增加过滤字段前缀
//                            .addFieldSuffix("_field") // 增加过滤字段后缀
                        .addInclude(Tables) // 表匹配

                        // Entity 策略配置
                        .entityBuilder()
                        .superClass(SUPER_CLASS)
                        .addSuperEntityColumns(SUPER_ENTITY_COLUMN_LIST)
                        .enableFileOverride()
                        .enableLombok() // 开启lombok
                        .enableChainModel() // 链式
                        .enableRemoveIsPrefix() // 开启boolean类型字段移除is前缀
                        .enableTableFieldAnnotation() // 开启生成实体时生成的字段注解
//                                        .versionColumnName("version") // 乐观锁数据库字段
//                                        .versionPropertyName("version") // 乐观锁实体类名称
//                                        .logicDeleteColumnName("delflag") // 逻辑删除数据库中字段名
//                                        .logicDeletePropertyName("delFlag") // 逻辑删除实体类中的字段名
                        .naming(NamingStrategy.underline_to_camel) // 表名 下划线 -》 驼峰命名
                        .columnNaming(NamingStrategy.underline_to_camel) // 字段名 下划线 -》 驼峰命名
                        // .idType(IdType.ASSIGN_ID) // 主键生成策略 雪花算法生成id
                        .formatFileName("%sDO") // Entity 文件名称
//                                        .addTableFills(new Column("create_time", FieldFill.INSERT)) // 表字段填充
//                                        .addTableFills(new Column("update_time", FieldFill.INSERT_UPDATE)) // 表字段填充
                        //.enableColumnConstant()
                        //.enableActiveRecord()//MPlus中启用ActiveRecord模式，生成的实体类会继承activerecord.Model类，直接进行数据库操作

                        // Controller 策略配置
                        .controllerBuilder()
                        .enableFileOverride()
//                        .enableHyphenStyle()
                        .enableRestStyle() // 开启@RestController
                        .formatFileName("%sController") // Controller 文件名称

                        // Service 策略配置
                        .serviceBuilder()
                        .enableFileOverride()
                        .formatServiceFileName("%sService") // Service 文件名称
                        .formatServiceImplFileName("%sServiceImpl") // ServiceImpl 文件名称

                        // Mapper 策略配置
                        .mapperBuilder()
                        .enableFileOverride()
                        .enableMapperAnnotation() // 开启@Mapper
                        .enableBaseColumnList() // 启用 columnList (通用查询结果列)
                        .enableBaseResultMap() // 启动resultMap
                        .formatMapperFileName("%sMapper") // Mapper 文件名称
                        .formatXmlFileName("%sMapper");// Xml 文件名称
    }

    private static Consumer<PackageConfig.Builder> configPackage() {
        return builder ->
                builder.parent(CODE_PARENT_PACKAGE) // 设置父包名
                        // .moduleName(CODE_MODULE_NAME) // 设置父包模块名
                        .controller(CONTROLLER_PACKAGE)
                        .entity(ENTITY_PACKAGE)
                        .service(SERVICE_PACKAGE)
                        .serviceImpl(SERVICE_IMPL_PACKAGE)
                        .mapper(MAPPER_PACKAGE)
                        //.xml("mapper") // 这个会生成在/src/main/java的包下
                        .pathInfo(Collections.singletonMap(OutputFile.xml, XML_RESOURCE_PACKAGE));// 设置mapperXml生成路径
    }

    private static Consumer<DataSourceConfig.Builder> configDataSource() {
        return builder ->
                builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
                    int typeCode = metaInfo.getJdbcType().TYPE_CODE;
                    if (typeCode == Types.SMALLINT) {
                        // 自定义类型转换
                        return DbColumnType.INTEGER;
                    }
                    if (typeCode == Types.DATE) {
                        return DbColumnType.LOCAL_DATE_TIME;
                    }
                    if (typeCode == Types.TINYINT) {
                        return DbColumnType.INTEGER;
                    }
                    if (typeCode == Types.BIT) {
                        return DbColumnType.BOOLEAN;
                    }
                    return typeRegistry.getColumnType(metaInfo);
                });
    }

    private static Consumer<GlobalConfig.Builder> configGlobal() {
        return builder -> {
            builder.enableSpringdoc()
                    .author(CODE_AUTHOR) // 设置作者
//                            .enableSwagger() // 开启 swagger 模式
                    .dateType(DateType.ONLY_DATE) // 时间策略
                    .commentDate(COMMENT_DATE_PATTERN) // 注释日期
                    .outputDir(CODE_OUTPUT_DIR) // 输出目录
                    .disableOpenDir();// 生成后禁止打开所生成的系统目录
        };
    }
}

